home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 3_0 / SPIRO_SO / SPIRO.C < prev    next >
Text File  |  1989-06-18  |  22KB  |  885 lines

  1. /*
  2. **                            SPIRO.C
  3. **                        John M. Nalezny    
  4. **    
  5. **    This is a spirograph simulation program.  You get to select
  6. **    The sizes of the two gears, the place to put the pen. Due to excessive
  7. **    use of sine/cosine, the first version is expected to be a dog.
  8. **    The use of a sine cache should clear that up. Those of you with
  9. **    Math coprocessors probably won't know the difference, but those
  10. **    of us without them should be delighted. P.S. the sine cache is
  11. **  about 5 times faster than making the function call every time.
  12. **
  13. **       This program uses a window as a non-modal dialog box to handle the 
  14. **  settings, like gear size, color, and pause state.  If I had a color
  15. **  system, I would also want to add color selections, and I might anyway.
  16. **  I just hate to try to debug programs that use hardware I don't have.   
  17. **       This program also is multi-finder friendly. When it is drawing, 
  18. **  it gives up about 30 percent of the time to background stuff.  At
  19. **  other times, it gives up about 95 percent. Seems like a good idea 
  20. **  with version 7.0 comming (everybody in multifinder)
  21. **        How do you like that About Box?  Thanks to the Symantec people
  22. ** for that one.
  23. **
  24. **    History:
  25. **    May 29 89  JMN
  26. **        Program born.
  27. **
  28. **    June 3 89 JMN
  29. **        make sure It can't go outside the box, and add growIcon
  30. **    
  31. **    June 10 89 JMN
  32. **        Multifinder friendly, and refreshing screen properly.
  33. **
  34. **    June 17 89 JMN
  35. **        Now it does a formally correct spirograph curve.  Also, cured
  36. **    roundoff desease by using nominator and denominator stuff.
  37. */
  38.  
  39.    /* include lots of stuff.  */
  40. #include <QuickDraw.h>
  41. #include <MacTypes.h>
  42. #include <FontMgr.h>
  43. #include <WindowMgr.h>
  44. #include <MenuMgr.h>
  45. #include <TextEdit.h>
  46. #include <DialogMgr.h>
  47. #include <EventMgr.h>
  48. #include <DeskMgr.h>
  49. #include <FileMgr.h>
  50. #include <ToolboxUtil.h>
  51. #include <ControlMgr.h>
  52. #include <math.h>
  53. #include <storage.h>
  54. #include <unix.h>
  55. #include <PrintMgr.h>
  56. #include "ftrig.h"
  57.  
  58. /* I probably include too much stuff, but I find it easier to include 
  59. ** too much and just not worry about it 
  60. */
  61.   
  62.  
  63. #define NIL 0L
  64. #define VISIBLE 1
  65.  
  66. #define APPLE_MENU 129
  67. #define FILE_MENU  130
  68. #define EDIT_MENU  131
  69.  
  70. #define PRINT_M     1
  71. #define QUIT_M      2
  72.  
  73. #define CUT_M        2
  74. #define COPY_M        3
  75. #define PASTE_M        4
  76. #define CLEAR_M        5
  77.  
  78.  
  79. #define DIALOG_ID   129
  80. #define ABOUT_BOX_ID 128
  81.  
  82. #define STOP 1
  83. #define GO 2
  84.  
  85. #define PEN_POS_MAX 20
  86.  
  87. #define WINDOW_ID 128
  88.  
  89.     
  90.   int errno;    
  91.   WindowPtr draw_window, dlg_window;
  92.   WindowRecord draw_window_record, dlg_window_record;
  93.   int quit_whole_program = 0; /* global flag */
  94.   MenuHandle apple_menu_h;
  95.   MenuHandle file_menu_h;
  96.   MenuHandle edit_menu_h;
  97.  
  98.   ControlHandle pause_control;
  99.   ControlHandle gear_1_size_control;
  100.   ControlHandle gear_speed_control;
  101.   ControlHandle gear_2_size_control;
  102.   ControlHandle pen_position_control;
  103.   
  104.   long gear_1_speed_num, gear_1_speed_denom;
  105.   int point_number;
  106.   int gear_1_size = 36;
  107.   int gear_2_size = 40;
  108.   int gear_2_speed = 10;
  109.   int pen_position = PEN_POS_MAX;
  110.   int scale_nom, scale_denom;
  111.   int pause_state = STOP;
  112.   int last_x, last_y;
  113.   
  114.   int in_foreground = 1; /* are we in the foreground? */
  115.   int wne_implemented; /* is wait next_event implemented? */
  116.     
  117.   double ftrig(int, int);
  118.   
  119.   PicHandle spiro_pic = NIL;
  120.  
  121. void init_managers()
  122. {
  123.     int i;
  124.     
  125.     MaxApplZone();
  126.     for ( i = 0 ; i < 10 ; i++ )
  127.         MoreMasters();
  128.                 /* Seems like a good practice to do this */
  129.     InitGraf(&thePort);
  130.     InitFonts();
  131.     InitWindows();    
  132.     FlushEvents(everyEvent,0);
  133.      InitWindows();
  134.     InitCursor();
  135.     InitMenus();  /* init menu bar stuff */
  136.     TEInit();    
  137.     InitDialogs(NIL);  /* I don't want to handle a system reset yet */
  138. }    
  139.  
  140. void setup_fake_dialog()
  141. {
  142.     Handle w_dim;  /* window dimentions resource */
  143.     long res_type, dummy;
  144.     int *ptr;
  145.  
  146.     dlg_window = GetNewWindow( DIALOG_ID, &dlg_window_record, -1L);
  147.                     /* get resource window */
  148.     sprintf(&res_type, "WDIM");
  149.     w_dim = GetResource(res_type, DIALOG_ID);
  150.     HLock(w_dim);
  151.     ptr = (int*)(*w_dim);    
  152.     MoveWindow(dlg_window, *(ptr + 1), *ptr, TRUE);
  153.     SizeWindow(dlg_window, *(ptr + 3) - *(ptr + 1), 
  154.             *(ptr + 2) - *ptr, TRUE);
  155.     HUnlock(w_dim);
  156.     
  157.     ShowWindow(dlg_window);    
  158.     SetPort(dlg_window);
  159. }
  160.  
  161.  
  162. void setup_draw_window()
  163. {
  164.     Handle w_dim;  /* window dimentions resource */
  165.     long res_type, dummy;
  166.     int *ptr;
  167.     
  168.     draw_window = GetNewWindow( WINDOW_ID, &draw_window_record, -1L);
  169.                     /* get resource window */
  170.     sprintf(&res_type, "WDIM");
  171.     w_dim = GetResource(res_type, WINDOW_ID);
  172.     HLock(w_dim);
  173.     ptr = (int*)(*w_dim);    
  174.     MoveWindow(draw_window, *(ptr + 1), *ptr, TRUE);
  175.     SizeWindow(draw_window, *(ptr + 3) - *(ptr + 1), 
  176.             *(ptr + 2) - *ptr, TRUE);
  177.     HUnlock(w_dim);
  178.     
  179.     ShowWindow(draw_window);
  180.     pause_state = STOP;
  181.     SetPort(dlg_window);
  182.     update_fake_dialog();
  183.     calculate_scale();
  184. }
  185.  
  186.  
  187.  
  188. remember_window_positions()
  189. {
  190.     Handle w_dim;  /* window dimentions resource */
  191.     long res_type, dummy;
  192.     int *ptr;
  193.     Point pt;
  194.     
  195.     sprintf(&res_type, "WDIM"); 
  196.     w_dim = GetResource(res_type, DIALOG_ID); /* start with dialog window*/
  197.     HLock(w_dim);
  198.     ptr = (int*)(*w_dim);
  199.     SetPort(dlg_window);
  200.     pt.h = pt.v = 0; /* upper left hand corner */
  201.     LocalToGlobal(&pt);
  202.     *ptr = pt.v;
  203.     *(ptr + 1) = pt.h;
  204.     pt.h = dlg_window->portRect.right;
  205.     pt.v = dlg_window->portRect.bottom;
  206.     LocalToGlobal(&pt);
  207.     *(ptr + 2) = pt.v;
  208.     *(ptr + 3) = pt.h;        
  209.     ChangedResource(w_dim);
  210.     WriteResource(w_dim);             /* done with dialog window */
  211.     HUnlock(w_dim);
  212.     
  213.     w_dim = GetResource(res_type, WINDOW_ID); /* start with draw window*/
  214.     HLock(w_dim);
  215.     ptr = (int*)(*w_dim);
  216.     SetPort(draw_window);
  217.     pt.h = pt.v = 0; /* upper left hand corner */
  218.     LocalToGlobal(&pt);
  219.     *ptr = pt.v;
  220.     *(ptr + 1) = pt.h;
  221.     pt.h = draw_window->portRect.right;
  222.     pt.v = draw_window->portRect.bottom;
  223.     LocalToGlobal(&pt);
  224.     *(ptr + 2) = pt.v;
  225.     *(ptr + 3) = pt.h;        
  226.     ChangedResource(w_dim);
  227.     WriteResource(w_dim);             /* done with draw window */
  228.     HUnlock(w_dim);
  229.  
  230. }
  231.  
  232.  
  233. update_fake_dialog()
  234. {
  235.     Rect box;
  236.     char txt[256];
  237.     
  238.     KillControls(dlg_window); /* clear the decks of old controls */
  239.      EraseRect(&dlg_window->portRect);
  240.         
  241.     SetRect(&box, 5,5,120,25); 
  242.     if (pause_state == GO)
  243.         sprintf(txt, "\pSTOP");
  244.     else
  245.         sprintf(txt, "\pGO");
  246.     pause_control = NewControl(dlg_window, &box, txt, VISIBLE,0,0,0, 
  247.             pushButProc, 0L);
  248.             
  249.     MoveTo(5,45);
  250.     DrawString("\pStationary Gear Size");    
  251.     SetRect(&box, 5,49,120, 65); 
  252.     gear_1_size_control = NewControl(dlg_window, &box, "\pHello", VISIBLE,
  253.             gear_1_size,20,100, scrollBarProc, 0L);
  254.     
  255.     MoveTo(5,85);
  256.     DrawString("\pMoving Gear Size");    
  257.     SetRect(&box, 5, 89,120,105); 
  258.     gear_2_size_control = NewControl(dlg_window, &box, "\pHello", VISIBLE,
  259.             gear_2_size,20,100, scrollBarProc, 0L);
  260.  
  261.     MoveTo(5,125);
  262.     DrawString("\pSpeed");    
  263.     SetRect(&box, 5,129,120, 145); /* top left bottom right */    
  264.     gear_speed_control = NewControl(dlg_window, &box, "\pHello", VISIBLE,
  265.             gear_2_speed,0,25, scrollBarProc, 0L);
  266.             
  267.     MoveTo(5,165);
  268.     DrawString("\pPen Position");    
  269.     SetRect(&box, 5,169,120, 185); /* top left bottom right */    
  270.     pen_position_control = NewControl(dlg_window, &box, "\pHello", VISIBLE,
  271.             pen_position,0,PEN_POS_MAX, scrollBarProc, 0L);
  272.         
  273.     calculate_gear_speeds();
  274.     
  275. }
  276.  
  277.  
  278.  
  279. void setup_menus()
  280. {
  281.     char apple[256], txt[256];
  282.     
  283.     sprintf(apple,"\p%c", appleMark);
  284.      apple_menu_h = NewMenu(APPLE_MENU, apple); 
  285.     AppendMenu(apple_menu_h, "\pAbout Spiro;(-");
  286.     AddResMenu(apple_menu_h, 'DRVR');
  287.     InsertMenu(apple_menu_h, 0);  /* this should be the applemenu */
  288.     
  289.     sprintf(txt,"\pFile");
  290.      file_menu_h = NewMenu(FILE_MENU, txt); 
  291.     AppendMenu(file_menu_h, "\pPrint/P;Quit/Q");
  292.     InsertMenu( file_menu_h, 1);  
  293.     
  294.     sprintf(txt,"\pEdit");
  295.      edit_menu_h = NewMenu(EDIT_MENU, txt); 
  296.     AppendMenu(edit_menu_h, "\pUndo/Z;(-;Cut/X;Copy/C;Paste/V;Clear");
  297.     InsertMenu( edit_menu_h, 2); 
  298.     
  299.     DrawMenuBar();    
  300.  
  301. }
  302.  
  303.  
  304. void do_drawing()
  305. {
  306.     long temp;
  307.     int x,y, gear_1_angle, gear_2_angle;
  308.     GrafPtr old_port;
  309.     
  310.     if (pause_state == GO)
  311.     {
  312.         GetPort(&old_port);
  313.         SetPort(draw_window);
  314.         
  315.         MoveTo(last_x,last_y); /* where were we? */    
  316.         temp = ( point_number * gear_1_speed_num) / gear_1_speed_denom;
  317.         gear_1_angle = temp % 360;
  318.         gear_2_angle = ((gear_2_speed * point_number) % 360) + gear_1_angle;
  319.         gear_2_angle = gear_2_angle % 360;
  320.         calculate_point(&x, &y, gear_1_angle, gear_2_angle);                        
  321.         LineTo(x,y);
  322.         if( (point_number != 0) && (gear_1_angle == 0) && 
  323.                     (gear_2_angle == 0) )
  324.             stop_drawing();
  325.         last_x = x;
  326.         last_y = y;    
  327.         point_number++;
  328.         SetPort(old_port);
  329.     }    
  330. }
  331.  
  332. stop_drawing()
  333. {
  334.     GrafPtr old_port;
  335.     
  336.     GetPort(&old_port);
  337.     SetPort(draw_window);
  338.     SysBeep(0);
  339.     HidePen();
  340.     ClosePicture();
  341.     pause_state = STOP;
  342.     SetPort(old_port);
  343.     SetPort(dlg_window);
  344.     update_fake_dialog();
  345. }
  346.  
  347. print_picture( pic, r)
  348. PicHandle pic;
  349. Rect *r;
  350. {    
  351.     TPPrPort printer_port;
  352.     GrafPtr savePort;
  353.     TPrStatus prStatus;
  354.      THPrint hPrint = NIL;
  355.     RgnHandle clip_region;
  356.     Rect c_rect;
  357.             
  358.     PrOpen();  /* first print manager call to make (II 154) */
  359.     PrintDefault (hPrint = (TPrint **) NewHandle( sizeof( TPrint)));
  360.                  /* prepare standard print record */
  361.     PrDrvrOpen();
  362.         
  363.     PrStlDialog(hPrint); /* style dialog box */
  364.     PrJobDialog(hPrint); /* job dialog box */    
  365.  
  366.     GetPort(&savePort);                
  367.     printer_port = PrOpenDoc(hPrint, NIL, NIL);
  368.     PrOpenPage(printer_port, NIL);
  369.     
  370.             /* I set up a clip region so that the horizontal and vertical
  371.                 lines associated with the grow icon don't get printed */
  372.     clip_region = NewRgn();
  373.     OpenRgn();
  374.     c_rect.top = r->top;
  375.     c_rect.left = r->left;
  376.     c_rect.bottom = r->bottom - 20;
  377.     c_rect.right = r->right - 20;
  378.     FrameRect(&c_rect);
  379.     CloseRgn(clip_region);    
  380.     printer_port->gPort.clipRgn = clip_region;
  381.     
  382.         DrawPicture(pic, r);
  383.     
  384.     PrClosePage(printer_port);
  385.                 
  386.     PrCloseDoc(printer_port);
  387.     DisposeRgn(clip_region);
  388.     PrPicFile (hPrint, NIL, NIL, NIL, &prStatus);
  389.     
  390.     PrClose();                
  391.     SetPort(savePort);
  392. }
  393.  
  394.  
  395. refresh_window()
  396. {
  397.  
  398.     if (pause_state == STOP) /* only redraw when we are done drawing */
  399.     {
  400.         SetPort(draw_window);
  401.         if (spiro_pic != NIL)
  402.             DrawPicture(spiro_pic, &draw_window->portRect); 
  403.         ShowPen();
  404.     }
  405.  
  406. }
  407.  
  408. do_command(x)
  409. long x;
  410. {
  411.     Str255 name;
  412.     long pict_type, dummy;
  413.     DialogPtr my_dialog;
  414.     
  415.     sprintf(&pict_type, "PICT");
  416.     
  417.     if (HiWord(x) != 0)  /* if we have a real menu event. . . */
  418.         switch (HiWord(x))
  419.         {
  420.             case APPLE_MENU:
  421.                 if (LoWord(x) == 1)
  422.                 {
  423.                     aboutcommand (); /* nifty about box from symantec */
  424.                 }
  425.                 else
  426.                 {
  427.                     GetItem(apple_menu_h, LoWord(x), name);
  428.                     OpenDeskAcc(name); 
  429.                     SetPort(draw_window);
  430.                 }
  431.                 break;
  432.             case FILE_MENU:
  433.                 switch (LoWord(x))
  434.                 {
  435.                     case PRINT_M:
  436.                         print_picture( spiro_pic, &draw_window->portRect);
  437.                         break;
  438.                     case QUIT_M:
  439.                          quit_whole_program = 1;  /* quit flag */
  440.                          break;
  441.                   } /* end of case for filemenu */
  442.                  break; /* break after case file_menu */
  443.             case EDIT_MENU:
  444.                 if  (0 == SystemEdit(LoWord(x) - 1) )
  445.                     switch (LoWord(x))
  446.                     {
  447.                         case CUT_M:
  448.                         case COPY_M:
  449.                             ZeroScrap();
  450.                             PutScrap(GetHandleSize(spiro_pic),
  451.                                  pict_type, *spiro_pic);
  452.                             UnloadScrap();
  453.                             break;    
  454.                         case PASTE_M:
  455.                             SysBeep(10);
  456.                             break;
  457.                         case CLEAR_M:
  458.                             ZeroScrap();
  459.                             UnloadScrap();
  460.                             break;
  461.                     }
  462.                 break;  /* break after case edit_menu */    
  463.         }  /* end of switch for hiword */    
  464.     HiliteMenu(0);  /* unhilight menus */
  465.  
  466. }
  467.  
  468. calculate_gear_speeds()
  469. {
  470.     gear_1_speed_num = (long)gear_2_speed * (long)gear_2_size; 
  471.     gear_1_speed_denom = (long)(gear_1_size) ;
  472.     
  473. }
  474.  
  475.  
  476. calculate_scale()
  477. {
  478.  
  479.     int size_x, size_y;
  480.  
  481.     /* the goal here is to get a nominator and denominator such that
  482.     ** the images fit on the screen.  
  483.     */
  484.  
  485.     size_x = (draw_window->portRect.right - 
  486.                 draw_window->portRect.left) - 25;
  487.                 
  488.     size_y = (draw_window->portRect.bottom - 
  489.                 draw_window->portRect.top) - 25;
  490.                 
  491.     if (size_x > size_y)
  492.         scale_nom = size_y / 2;
  493.     else
  494.         scale_nom = size_x / 2;            
  495.     
  496.     scale_denom = gear_1_size + gear_2_size + gear_2_size;
  497.     
  498. }
  499.  
  500. calculate_midpoint(x,y)
  501. int *x, *y;
  502. {
  503.     *x = (draw_window->portRect.left + 
  504.                 draw_window->portRect.right - 16) >> 1;
  505.     *y = (draw_window->portRect.top + 
  506.                 draw_window->portRect.bottom - 16) >> 1;
  507. }
  508.  
  509. draw_gears()
  510. {
  511.     PenState pn_state;
  512.     Rect box;
  513.     int mid_x, mid_y, temp, temp_x, temp_y;
  514. #if 0        
  515.     GetPenState(&pn_state);
  516.     PenMode(patXor);
  517.     calculate_midpoint(&mid_x, &mid_y);
  518.     temp = (int) (((long)gear_1_size * (long)scale_nom) / 
  519.             (long)scale_denom);
  520.     box.top = mid_y - temp; 
  521.     box.bottom = mid_y + temp;
  522.     box.left = mid_x - temp;
  523.     box.right = mid_x + temp;
  524.     FrameOval(&box);
  525.     temp_x = (int)( ftrig (FTRIG_SINE, gear_1_angle ) * 
  526.                 (gear_1_size + gear_2_size )); 
  527.     temp_y = (int)( ftrig (FTRIG_COS,  gear_1_angle ) * 
  528.                 (gear_1_size + gear_2_size )); 
  529.     temp_x = (int) (((long)temp_x * (long)scale_nom) / 
  530.             (long)scale_denom);
  531.     temp_y = (int) (((long)temp_y * (long)scale_nom) / 
  532.             (long)scale_denom);
  533.     mid_x += temp_x;
  534.     mid_y += temp_y;
  535.     temp = (int) (((long)gear_2_size * (long)scale_nom) / 
  536.             (long)scale_denom);
  537.     box.top = mid_y - temp; 
  538.     box.bottom = mid_y + temp;
  539.     box.left = mid_x - temp;
  540.     box.right = mid_x + temp;
  541.     FrameOval(&box);    
  542.     
  543.     SetPenState(&pn_state);
  544. #endif
  545. }
  546.  
  547. /*    CALCULATE POINT
  548. **        does the actual spirograph calculation, using global variables
  549. **   gear_1_size, gear_2_size. 
  550. */    
  551. calculate_point(x,y, gear_1_angle, gear_2_angle)
  552. int *x, *y, gear_1_angle, gear_2_angle;
  553. {
  554.         int temp_x, temp_y, mid_x, mid_y;
  555.         temp_x = (int)( ftrig (FTRIG_SINE, gear_1_angle ) * 
  556.                     (gear_1_size + gear_2_size )); 
  557.         temp_y = (int)( ftrig (FTRIG_COS,  gear_1_angle ) * 
  558.                     (gear_1_size + gear_2_size )); 
  559.         temp_x += (int)((ftrig (FTRIG_SINE, gear_2_angle ) * 
  560.                     gear_2_size * pen_position) / PEN_POS_MAX);
  561.         temp_y += (int)((ftrig (FTRIG_COS,  gear_2_angle ) * 
  562.                     gear_2_size * pen_position) / PEN_POS_MAX); 
  563.         temp_y = (int) (((long)temp_y * (long)scale_nom) / (long)scale_denom);
  564.         temp_x = (int) (( (long)temp_x * (long)scale_nom) / (long)scale_denom);        
  565.         calculate_midpoint(&mid_x, &mid_y);
  566.         *x = temp_x + mid_x;
  567.         *y = temp_y + mid_y;
  568. }
  569.  
  570. control_hit( pt)
  571. Point pt;
  572. {
  573.     ControlHandle which_control;
  574.     int part_code;
  575.     int value;
  576.     Rect r;
  577.     
  578.     if (FindControl( pt ,dlg_window, &which_control))
  579.     {    /* if we can find a control that was hit */
  580.         part_code = TrackControl(which_control, pt, NIL); 
  581.         if (part_code != 0) /* if they really hit it */
  582.         {  /* cant use switch here because controlHandle != int */
  583.              if  (which_control == pause_control)
  584.             {
  585.                     if (pause_state == GO)
  586.                     {
  587.                         stop_drawing();
  588.                     }
  589.                     else
  590.                     {
  591.                         point_number = 0;
  592.                         pause_state = GO;
  593.                         SetPort(draw_window);
  594.                         EraseRect(&draw_window->portRect);
  595.                         InvalRect(&draw_window->portRect);
  596.                                                 
  597.                         calculate_scale();
  598.                         calculate_gear_speeds();
  599.                         draw_gears();
  600.                         calculate_point(&last_x, &last_y, 0, 0);
  601.                         point_number++;
  602.  
  603.                         if (spiro_pic != NIL)
  604.                             KillPicture(spiro_pic);    
  605.                         spiro_pic = OpenPicture(&draw_window->portRect);
  606.                         ShowPen();
  607.                     }
  608.                     SetPort(dlg_window);
  609.                     update_fake_dialog();
  610.             }
  611.  
  612.             if (which_control == gear_1_size_control)
  613.                 handle_scroll_bar(which_control,part_code, &gear_1_size);
  614.                 
  615.             if (which_control == gear_2_size_control)
  616.                 handle_scroll_bar(which_control,part_code, &gear_2_size);
  617.                 
  618.             if (which_control == gear_speed_control)
  619.                 handle_scroll_bar(which_control,part_code, &gear_2_speed);
  620.                 
  621.             if (which_control == pen_position_control)
  622.                 handle_scroll_bar(which_control,part_code, &pen_position);
  623.             calculate_gear_speeds();
  624.             calculate_scale();    
  625.         } /* end of if partcode != 0 */
  626.      } /* end of FindControl */
  627. }
  628.  
  629. handle_scroll_bar(which_control, part_code, rtn)
  630. ControlHandle which_control;
  631. int part_code, *rtn;
  632. {
  633.  
  634. int value;
  635.  
  636.     value = GetCtlValue(which_control);
  637.     switch (part_code)
  638.     {
  639.         case inDownButton:
  640.             if (value < GetCtlMax(which_control))
  641.                 value++;
  642.             SetCtlValue(which_control, value);
  643.             break;
  644.         case inUpButton:
  645.             if (value > GetCtlMin(which_control))
  646.                 value--;
  647.             SetCtlValue(which_control, value);
  648.             break;
  649.         case inPageDown:
  650.             if (value < GetCtlMax(which_control) - 5)
  651.                 value += 5;
  652.             SetCtlValue(which_control, value);
  653.             break;
  654.         case inPageUp:
  655.             if (value > GetCtlMin(which_control) + 5)
  656.                 value -= 5;
  657.             SetCtlValue(which_control, value);
  658.             break;
  659.         case inThumb:
  660.             value = GetCtlValue(which_control);
  661.             break;
  662.     }/* end of switch */
  663.     *rtn = value;
  664. }    
  665.  
  666. handle_App4Evt(my_event)
  667. EventRecord *my_event;
  668. {
  669.     static WindowPtr former_front_window;
  670.     
  671.     if ( (my_event->message & 0xff000000) == 0x01000000)
  672.     { /* if it is a genuine multifinder app4evt ...*/
  673.         if (my_event->message & 0x000001)
  674.         { /* if it is a resume event */
  675.             in_foreground = TRUE;
  676.             HiliteWindow(former_front_window, TRUE);
  677.             UnloadScrap();
  678.         }
  679.         else    
  680.         { /* else it must be a suspend event */
  681.             in_foreground = FALSE;
  682.             former_front_window = FrontWindow();
  683.             HiliteWindow(former_front_window, FALSE);
  684.             LoadScrap();
  685.         }
  686.     }
  687.  
  688. }
  689.  
  690.  
  691. my_get_event(my_event)
  692. EventRecord *my_event;
  693. {
  694.     long wait_time;
  695.     
  696.     if (!wne_implemented)
  697.     {
  698.         SystemTask(); /* make sure someone else get a hunk of time */
  699.         return(GetNextEvent(everyEvent, my_event)); 
  700.     }
  701.     else /* else wait_next_event is here */
  702.     {
  703.         wait_time = 1L; /* the default is to give away a small piece of
  704.             time */
  705.         if ( (in_foreground) && (pause_state == STOP))
  706.             wait_time = 20L; /* give up a larger amount of time */
  707.         if (!in_foreground)
  708.             wait_time = 10000L; /* give up lots of time in background */ 
  709.         
  710.         return(WaitNextEvent(everyEvent, my_event, wait_time, NIL));
  711.                             /* NIL refers to a cursor region */
  712.     }
  713.     
  714. }
  715.  
  716.  
  717. check_events()
  718. {
  719.     EventRecord my_event;
  720.     Point location;
  721.     WindowPtr which_window;
  722.     ControlHandle which_control;
  723.     Rect bounds;
  724.     char the_key;
  725.     GrafPtr old_port;
  726.     long new_size;
  727.          
  728.     if (!my_get_event(&my_event)) /* uses wait_next_event if it can */
  729.         return(0);  /* if no event, go draw something maybe */
  730.     if (my_event.what == mouseDown)
  731.         switch(FindWindow(my_event.where, &which_window) )
  732.         {
  733.              case inDesk: 
  734.                 SysBeep(1);
  735.                 break;
  736.             case inSysWindow:  /* someone else's window */
  737.                 SystemClick(&my_event, which_window); /* pass it on */
  738.                 break;
  739.             case inGoAway:     /* if they want to go away */
  740.                 if (TrackGoAway(which_window, my_event.where))
  741.                       quit_whole_program = 1;
  742.                  break;
  743.             case inMenuBar: 
  744.                 do_command(MenuSelect(my_event.where) );
  745.                 break;
  746.             case inContent:   /* if in content of current window */
  747.                 if (which_window == dlg_window)
  748.                 {
  749.                     GetPort(&old_port);
  750.                     if (old_port != dlg_window)
  751.                         SelectWindow(which_window);
  752.                     location = my_event.where;
  753.                     SetPort(dlg_window);  /* make dialog the current port */
  754.                     GlobalToLocal(&location);
  755.                     control_hit(location);
  756.                 }
  757.                 if (which_window == draw_window)
  758.                 {
  759.                     SelectWindow(which_window);
  760.                 }
  761.                 break;
  762.              case inDrag:
  763.                  if( (which_window == draw_window) || 
  764.                          (which_window == dlg_window))
  765.                  { 
  766.                      SetRect( &bounds, 15, 25, screenBits.bounds.right - 15,
  767.                                  screenBits.bounds.bottom - 15);
  768.                      DragWindow(which_window, my_event.where,  &bounds);
  769.                  }
  770.                  break;
  771.              case inGrow:
  772.                  if (which_window == draw_window)
  773.                  {
  774.                      bounds.top = 50; /* min vert size */
  775.                      bounds.bottom = screenBits.bounds.bottom;/* max vert*/
  776.                      bounds.left = 50; /* min horiz size */
  777.                      bounds.right = screenBits.bounds.right; /* max horiz*/
  778.                      new_size = GrowWindow(draw_window, 
  779.                          my_event.where, &bounds);
  780.                      SizeWindow(draw_window, 
  781.                          LoWord(new_size), HiWord(new_size), TRUE);
  782.                      EraseRect(&draw_window->portRect); /*clear whole wind */
  783.                      InvalRect(&draw_window->portRect); /* update */
  784.                      calculate_scale();
  785.                  }
  786.             default:
  787.                  /* SysBeep(1);  */ /* why do we get here? */
  788.                  break;                
  789.          } /* end switch FindWindow */
  790.      else if (my_event.what == updateEvt) 
  791.      { 
  792.          if ((WindowPtr)my_event.message == draw_window) 
  793.          {
  794.               BeginUpdate(draw_window); 
  795.               refresh_window(); 
  796.               EndUpdate(draw_window);
  797.               DrawGrowIcon(draw_window);  
  798.          }
  799.          
  800.          if ((WindowPtr)my_event.message == dlg_window) 
  801.          {
  802.               GetPort(&old_port);
  803.               SetPort(dlg_window); 
  804.               BeginUpdate(dlg_window); 
  805.              update_fake_dialog(); 
  806.               EndUpdate( dlg_window);
  807.               SetPort(old_port); 
  808.               /* ??????????????????????????? */
  809.               BeginUpdate(dlg_window); /* to clear out update rgn */
  810.               EndUpdate(dlg_window); 
  811.          }
  812.  
  813.      } 
  814.  
  815.     else
  816.          if (my_event.what == activateEvt)
  817.         {
  818.             if (((WindowPtr)my_event.message == draw_window) && 
  819.                     (my_event.modifiers & activeFlag))
  820.             {
  821.                 SetPort(draw_window);  /* make my window the current port */
  822.                  DrawGrowIcon(draw_window);  
  823.             }
  824.             
  825.             if (((WindowPtr)my_event.message == draw_window) && 
  826.                     !(my_event.modifiers & activeFlag))
  827.             {
  828.                  DrawGrowIcon(draw_window); /* which clears out the icon */ 
  829.             }
  830.             
  831.  
  832.             if (((WindowPtr)my_event.message == dlg_window)   && 
  833.                     (my_event.modifiers & activeFlag)  )
  834.             {
  835.                 SetPort(dlg_window);  /* make my window the current port */
  836.             }
  837.  
  838.         }
  839.     else if (my_event.what == keyDown)
  840.     {
  841.         if( my_event.modifiers & cmdKey)
  842.         {
  843.             the_key = my_event.message & charCodeMask;
  844.             do_command(MenuKey(the_key));
  845.         }
  846.     }
  847.     else if (my_event.what == app4Evt)
  848.     {
  849.         handle_App4Evt(&my_event);
  850.     }        
  851.         
  852. }
  853.  
  854. void main()
  855. {
  856.  
  857.     init_managers();
  858.     setup_menus();
  859.     ftrig(FTRIG_INIT, 0);
  860.         
  861.     setup_fake_dialog();
  862.     setup_draw_window();    
  863.     wne_implemented = WNE_avail(); /* look for wait next event */
  864.     
  865.     while (!quit_whole_program)
  866.     {
  867.         /* The 2-function loop here is designed so that events can be
  868.         ** monitored even when drawing is in progress.  Other
  869.         ** programs need time on a regular basis, and can get it during
  870.         ** check_events().  This does not exactly speed up the drawing
  871.         ** process.  My goal is to allow a lengthy process to proceed,
  872.         ** and still give up time to other programs. Comments on
  873.         ** this method of doing things are invited. (I haven't seen
  874.         ** anyone else doing it this way, so I'm not sure it is best)
  875.         */
  876.         do_drawing(); /* this part does the actual drawing */
  877.         check_events(); /* this checks for events, and processes them */        
  878.     }
  879.     ftrig(FTRIG_END, 0);
  880.     remember_window_positions();
  881.  
  882. }
  883.  
  884.  
  885.